package com.yoouce.patchmng.controller;

import com.jcraft.jsch.JSchException;
import com.yoouce.patchmng.bean.JSONObject;
import com.yoouce.patchmng.bean.PatchInfo;
import com.yoouce.patchmng.bean.TreeObject;
import com.yoouce.patchmng.bean.UserInfo;
import com.yoouce.patchmng.init.SystemContants;
import com.yoouce.patchmng.util.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 补丁管理控制类 Created by administrator on 15-9-29.
 */
@Controller
public class PatchController extends BaseController {

    /**
     * 补丁的远程服务器路径
     */
    private static String PATCH_REMOTE_PATH = "/home/ycecs/patch/";

    /**
     * 上传补丁文件
     *
     * @param uploadFile 上传文件
     * @param patchInfo  上传补丁信息
     * @return 我的补丁树页面
     */
    @RequestMapping(value = "/uploadPatchFile")
    public String uploadPatchFile(
            @RequestParam(value = "uploadFile") CommonsMultipartFile uploadFile,
            PatchInfo patchInfo) {

        // 获取当前用户信息
        UserInfo userInfo = (UserInfo) getRequest().getSession()
                .getAttribute(SystemContants.USER_KEY);

        // 设置此次补丁文件的完整路径
        String patchPath = request.getSession().getServletContext().getRealPath(
                "/upload/patch/" + userInfo.getUserName() + "-" + DateTools
                        .getCurDay(DateTools.yyyyMMddHHmmss));
        String patchInstructionFile = userInfo.getUserName() + "-" + DateTools
                .getCurDay(DateTools.yyyyMMddHHmmss) + ".properties";
        LOG.info("uploadFile---------->" + uploadFile.getOriginalFilename());


        try {
            // 文件原名称
            String originFileName = uploadFile.getOriginalFilename();
            // 这里使用Apache的FileUtils方法来进行保存
            FileUtils.copyInputStreamToFile(
                    uploadFile.getInputStream(),
                    new File(patchPath + "/", originFileName));

            //在此文件夹下创建补丁说明文件
            File file = new File(patchPath + "/" + patchInstructionFile);
            if (file.createNewFile()) {
                LOG.info("在" + patchPath + "下创建补丁说明文件[" + patchInstructionFile + "]" + "成功！");
                patchInfo.setStatus(0);
                patchInfo.setPatchRealName(patchPath + "/" + originFileName);
                patchInfo.setPatchName(originFileName);
                patchInfo.setOpertor(userInfo.getUserName());
                patchInfo.setPatchFileName(userInfo.getUserName() + "-" + DateTools
                        .getCurDay(DateTools.yyyyMMddHHmmss));
                PropertiesUtils.writePropertiesFile(patchInfo, patchPath + "/" + patchInstructionFile);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("上传出错");
        }


        return "patchFileTreePage";
    }

    /**
     * 升级补丁前奏
     *
     * @param patchName 补丁名称
     * @return 升级页面
     */
    @RequestMapping(value = "/preUpdatePatch")
    public ModelAndView preUpdatePatch(@RequestParam(value = "patchName") String patchName) {
        String[] patchNames = StringUtils.split(patchName, "/");

        //获取最后一次/前的字符串为补丁文件的目录
        String path = StringUtils.substringBeforeLast(patchName, "/");
        //获取properties文件，此文件的名称和文件夹的名称一致
        String propertiesPath = request.getSession().getServletContext().getRealPath(
                "/upload" + path + "/" + patchNames[patchNames.length - 2] + ".properties");

        LOG.info("properties路径为：" + propertiesPath);
        //读取文件信息
        PatchInfo patchInfo = PropertiesUtils.readPropertiesFile(propertiesPath);
        request.setAttribute("patchInfo", patchInfo);
        return new ModelAndView("commitPatch");
    }

    /**
     * 补丁升级方法
     *
     * @param patchInfo 补丁信息
     * @return 成功页面和执行信息展示
     */
    @RequestMapping(value = "/updatePatch")
    public ModelAndView updatePatch(PatchInfo patchInfo) {

        Map<String, Object> resultMap = new HashMap<String, Object>();

        SftpUtil sfpUtil = new SftpUtil(patchInfo.getServerIp(), 22,
                patchInfo.getServerUserName(), patchInfo.getServerPassword());
        try {
            sfpUtil.sshSftpMkdir(PATCH_REMOTE_PATH + patchInfo.getPatchFileName());
        } catch (Exception e) {
            resultMap.put("msg", "创建目录出错：" + PATCH_REMOTE_PATH + patchInfo.getPatchFileName());
            return new ModelAndView("/patchResult", resultMap);
        }
        //将补丁包上传到服务器中
        String returnCode = this.scpPatchTar(patchInfo);
        if (!StringUtils.equals("200", returnCode)) {

            resultMap.put("msg", "连接服务器失败");
            return new ModelAndView("/patchResult", resultMap);
        }

        //登陆远程服务器，执行Python命令
        JSchUtil jSchUtil = new JSchUtil(patchInfo.getServerUserName(), patchInfo.getServerPassword(), patchInfo.getServerIp());

        try {
            jSchUtil.connect();
            String cmd = "python /home/ycecs/patch/patch.py -u "+PATCH_REMOTE_PATH + patchInfo.getPatchFileName() + "/" + patchInfo.getPatchName();
            LOG.info("开始连接执行脚本命令[" + cmd + "]");
            List<String> resultMsg = jSchUtil.execCmd(cmd);

            resultMap.put("msg", resultMsg);

        } catch (JSchException e) {

            resultMap.put("msg", "scp 连接命令失败");
            return new ModelAndView("/patchResult", resultMap);
        }
        //执行成功后刷新状态
        String propertiesPath = request.getSession().getServletContext().getRealPath(
                "/upload/patch/"+ patchInfo.getPatchFileName()+"/"+ patchInfo.getPatchFileName()+".properties");
        PropertiesUtils.modifyPropertiesValue(propertiesPath,"status","1");
        return new ModelAndView("/patchResult", resultMap);
    }

    /**
     * 补丁包回滚操作
     * @param patchInfo 补丁包信息
     * @return 返回成功页面和执行信息
     */
    @RequestMapping(value = "/rollbackPatch")
    public ModelAndView rollbackPatch(PatchInfo patchInfo) {

        Map<String, Object> resultMap = new HashMap<String, Object>();


        //登陆远程服务器，执行Python命令
        JSchUtil jSchUtil = new JSchUtil(patchInfo.getServerUserName(),
                patchInfo.getServerPassword(), patchInfo.getServerIp());
        try {
            jSchUtil.connect();
            String cmd = "python /home/ycecs/patch/patch.py -r "+PATCH_REMOTE_PATH + patchInfo.getPatchFileName() + "/" + patchInfo.getPatchName();
            LOG.info("开始连接执行脚本命令[" + cmd + "]");
            List<String> resultMsg = jSchUtil.execCmd(cmd);

            resultMap.put("msg", resultMsg);

        } catch (JSchException e) {

            resultMap.put("msg", "scp 连接命令失败");
            return new ModelAndView("/patchResult", resultMap);
        }

        return new ModelAndView("/patchResult", resultMap);
    }

    /**
     * 查找补丁文件
     * 根据目录查找当前用户的所有上传的补丁文件，非管理员用户，看不到非本用户的补丁文件
     *
     * @return 返回当前节点的信息
     */
    @RequestMapping(value = "/getPatchTree")
    @ResponseBody
    public List<TreeObject> getPatchFile() {
        String id = getRequest().getParameter("id");
        //获取session
        UserInfo userInfo = (UserInfo) getSession().getAttribute(SystemContants.USER_KEY);

        List<TreeObject> treeList = new ArrayList<TreeObject>();
        String patchPath = request.getSession().getServletContext().getRealPath(
                "/upload");

        String queryPath = "";
        if (StringUtils.isEmpty(id)) {
            queryPath = patchPath;
        } else {
            queryPath = patchPath + "/" + id;
        }

        File files = new File(queryPath);
        File[] tempList = files.listFiles();

        if (tempList != null) {


            for (File file : tempList) {
                TreeObject to = new TreeObject();

                if (StringUtils.isEmpty(id)) {
                    to.setId("/patch");
                } else {
                    to.setId(id + "/" + file.getName());
                }
                to.setText(file.getName());
                if (file.isFile()) {
                    LOG.info("文     件：" + file);
                }
                if (file.isDirectory()) {
                    to.setState("closed");
                    LOG.info("文件夹：" + file);
                }
                if (!"/patch".equals(id)) {
                    treeList.add(to);
                } else {
                    if (hasRole(userInfo, file.getName())) {
                        treeList.add(to);
                    }
                }
            }
        }
        return treeList;
    }

    /**
     * 判断用户是否具有目录的权限
     *
     * @param userInfo 用户信息
     * @param fileName 文件目录
     * @return boolean
     */
    private boolean hasRole(UserInfo userInfo, String fileName) {
        boolean result = false;
        if (userInfo != null) {

            if ("admin".equals(userInfo.getUserName())) {
                result = true;
            } else {
                if (fileName.contains(userInfo.getUserName())) {
                    result = true;
                }
            }

        }
        return result;
    }

    /**
     * 增加补丁包目录
     *
     * @return String
     */
    @RequestMapping(value = "/addPatchDirectory")
    @ResponseBody
    public JSONObject addPatchDirectory(@RequestParam(value = "currentPath") String currentPath,
                                        @RequestParam(value = "directoryName") String directoryName) {
        JSONObject result = new JSONObject();
        boolean success = makeDirs("/upload/" + currentPath + "/" + directoryName);
        result.setSuccess(success);
        return result;
    }


    /**
     * 创建指定文件夹
     *
     * @param filePath 文件夹路径
     * @return boolean
     */
    private boolean makeDirs(String filePath) {
        boolean result = false;
        String folderName = getRealPath(filePath);
        LOG.info(folderName);
        if (folderName == null || folderName.isEmpty()) {
            return false;
        }

        File folder = new File(folderName);

        result = folder.mkdirs();

        return result;
    }


    /**
     * 上传文件到指定路径
     * 路径地址为系统配置，只上传远程路径，本地不处理
     *
     * @param patchInfo 上传的目标路径
     * @throws throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    private String scpPatchTar(PatchInfo patchInfo) {
        SCPUtil scpUtil = new SCPUtil(patchInfo.getServerIp(), 22, patchInfo.getServerUserName(), patchInfo.getServerPassword());

        String returnCode = scpUtil.upLoadFile(PATCH_REMOTE_PATH + patchInfo.getPatchFileName(),
                patchInfo.getPatchRealName());
        return returnCode;

    }

}
